import numpy as np
import matplotlib.pyplot as plt

# 随机生成磁盘柱面请求序列
np.random.seed(0)  # 固定随机种子以便重现结果
request_sequences = [np.random.randint(0, 200, size=10) for _ in range(5)]
initial_positions = np.random.randint(0, 200, size=5)
seek_directions = np.random.choice([0, 1], size=5)

# 定义磁盘调度算法类
class DiskArm:
    def __init__(self, requests, initial, direction):
        self.requests = requests
        self.initial = initial
        self.direction = direction
        self.reset()

    def reset(self):
        self.position = self.initial
        self.remaining_requests = list(self.requests)
        self.seek_sequence = [self.position]
        self.seek_distance = 0

    def report(self):
        return self.seek_sequence, self.seek_distance

    def fcfs(self):
        self.reset()
        for request in self.requests:
            self.seek_distance += abs(self.position - request)
            self.position = request
            self.seek_sequence.append(self.position)
        return self.report()

    def sstf(self):
        self.reset()
        while self.remaining_requests:
            closest_request = min(self.remaining_requests, key=lambda x: abs(self.position - x))
            self.seek_distance += abs(self.position - closest_request)
            self.position = closest_request
            self.seek_sequence.append(self.position)
            self.remaining_requests.remove(closest_request)
        return self.report()

    def scan(self):
        self.reset()
        direction = self.direction
        while self.remaining_requests:
            if direction == 1:
                next_requests = [r for r in self.remaining_requests if r >= self.position]
                if not next_requests:
                    direction = 0
                    continue
            else:
                next_requests = [r for r in self.remaining_requests if r <= self.position]
                if not next_requests:
                    direction = 1
                    continue
            closest_request = min(next_requests, key=lambda x: abs(self.position - x))
            self.seek_distance += abs(self.position - closest_request)
            self.position = closest_request
            self.seek_sequence.append(self.position)
            self.remaining_requests.remove(closest_request)
        return self.report()

    def cscan(self):
        self.reset()
        direction = self.direction
        while self.remaining_requests:
            if direction == 1:
                next_requests = [r for r in self.remaining_requests if r >= self.position]
                if not next_requests:
                    self.position = 0
                    self.seek_distance += 199
                    self.seek_sequence.append(self.position)
                    continue
            else:
                next_requests = [r for r in self.remaining_requests if r <= self.position]
                if not next_requests:
                    self.position = 199
                    self.seek_distance += 199
                    self.seek_sequence.append(self.position)
                    continue
            closest_request = min(next_requests, key=lambda x: abs(self.position - x))
            self.seek_distance += abs(self.position - closest_request)
            self.position = closest_request
            self.seek_sequence.append(self.position)
            self.remaining_requests.remove(closest_request)
        return self.report()

    def look(self):
        self.reset()
        direction = self.direction
        while self.remaining_requests:
            if direction == 1:
                next_requests = [r for r in self.remaining_requests if r >= self.position]
                if not next_requests:
                    direction = 0
                    continue
            else:
                next_requests = [r for r in self.remaining_requests if r <= self.position]
                if not next_requests:
                    direction = 1
                    continue
            closest_request = min(next_requests, key=lambda x: abs(self.position - x))
            self.seek_distance += abs(self.position - closest_request)
            self.position = closest_request
            self.seek_sequence.append(self.position)
            self.remaining_requests.remove(closest_request)
        return self.report()

# 创建图表
fig, axs = plt.subplots(5, 5, figsize=(20, 20))

# 对每组数据应用所有算法并绘图
for i, (requests, initial, direction) in enumerate(zip(request_sequences, initial_positions, seek_directions)):
    disk_arm = DiskArm(requests, initial, direction)
    algorithms = {
        'FCFS': disk_arm.fcfs,
        'SSTF': disk_arm.sstf,
        'SCAN': disk_arm.scan,
        'C-SCAN': disk_arm.cscan,
        'LOOK': disk_arm.look
    }
    results = {name: algo() for name, algo in algorithms.items()}

    for j, (name, result) in enumerate(results.items()):
        sequence, distance = result
        axs[i, j].plot(sequence, range(len(sequence)), marker='o')
        axs[i, j].set_title(f'{name} (Seek Distance: {distance})')
        axs[i, j].set_ylabel('Step')
        axs[i, j].set_xlabel('Cylinder')

plt.tight_layout()
plt.show()
